import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.CyclicBarrier;

import javax.swing.text.html.HTMLDocument.Iterator;


public class TestRunner {
	
	// create the results map for all threads
	public static ResultsTable sharedTable = new ResultsTable();
	private static final int NUM_TESTS = 10;
	static CyclicBarrier barrier;
	
	// port configurations
	public static final int SMTP_587_PORT = 587;
	public static final int SMTP_25_PORT = 25;
	public static final int SMTP_465_PORT = 465;
	public static final int POP3_PORT = 110;
	public static final int POP3S_PORT = 995;
	public static final int IMAP_PORT = 143;
	public static final int IMAPS_PORT = 993;
	
	public static final String IPV6_HOST = "ipv6.google.com";
	
	public TestRunner(){
		barrier = new CyclicBarrier(13);
	}
	


	public ResultsTable startTests(){
		System.out.println("Now running TestRunner");
		
		// create each test class
//		InternetConnectivity inetTest = new InternetConnectivity(sharedTable, barrier, NUM_TESTS);
		TelnetTester telnetTest = new TelnetTester(sharedTable, barrier, NUM_TESTS);
		AllIMAPConnectivity imapTest = new AllIMAPConnectivity(sharedTable, barrier, NUM_TESTS);
		AllIMAPConnectivity imapsTest = new AllIMAPConnectivity(sharedTable, barrier, NUM_TESTS);
		AllPOP3Connectivity popTest = new AllPOP3Connectivity(sharedTable, barrier, NUM_TESTS);
		AllPOP3Connectivity popsTest = new AllPOP3Connectivity(sharedTable, barrier, NUM_TESTS);
		AllSMTPConnectivity smtp_25_Test = new AllSMTPConnectivity(sharedTable, barrier, NUM_TESTS);
		AllSMTPConnectivity smtp_587_Test = new AllSMTPConnectivity(sharedTable, barrier, NUM_TESTS);
		AllSMTPConnectivity smtp_465_Test = new AllSMTPConnectivity(sharedTable, barrier, NUM_TESTS);
		
		MulticastTester multicastTest = new MulticastTester(sharedTable, barrier, 3); 
		SSHTester sshTest = new SSHTester(sharedTable, barrier, 3);
		
		HTTPConnectivity httpTest = new HTTPConnectivity(sharedTable, barrier, NUM_TESTS);
		HTTPConnectivity httpsTest = new HTTPConnectivity(sharedTable, barrier, NUM_TESTS);
		
		// set properties of classes that need it
		smtp_25_Test.setProperties(SMTP_25_PORT);
		smtp_587_Test.setProperties(SMTP_587_PORT);
		smtp_465_Test.setProperties(SMTP_465_PORT);
		popTest.setProperties(POP3_PORT);
		popsTest.setProperties(POP3S_PORT);
		imapTest.setProperties(IMAP_PORT);
		imapsTest.setProperties(IMAPS_PORT);
		
		httpTest.setProperties("http://www.example.com", "http");
		httpsTest.setProperties("https://courseworks.columbia.edu", "https");
		
		// create a thread for each test
//		Thread inetThread = new Thread(inetTest);
		Thread telnetThread = new Thread(telnetTest);
		Thread imapThread = new Thread(imapTest);
		Thread imapsThread = new Thread(imapsTest);
		Thread popThread = new Thread(popTest);
		Thread popsThread = new Thread(popsTest);
		Thread smtp_25_Thread = new Thread(smtp_25_Test);
		Thread smtp_587_Thread = new Thread(smtp_587_Test);
		Thread smtp_465_Thread = new Thread(smtp_465_Test);
		Thread multicastThread = new Thread(multicastTest);
		Thread sshThread = new Thread(sshTest);
		Thread httpThread = new Thread(httpTest);
		Thread httpsThread = new Thread(httpsTest);
		
		
		// Start each thread 
//		inetThread.start();
		telnetThread.start();
		imapThread.start();
		imapsThread.start();
		popThread.start();
		popsThread.start();
		smtp_465_Thread.start();
		smtp_587_Thread.start();
		smtp_25_Thread.start();
		multicastThread.start();
		sshThread.start();
		httpThread.start();
		httpsThread.start();
		
		// wait for the barrier
		try {
			barrier.await();
		} catch (Exception e) {
			e.printStackTrace();
		}
	
		// Perform sequential tests here
		
		// ipv6 Test
		ConnectionStatus ipv6Status = new ConnectionStatus();
		IPv6Tester ip6 = new IPv6Tester();
		try {
			ipv6Status = ip6.ipv6Test(IPV6_HOST);
		} catch (Exception e) {
			ipv6Status.ipv6_status = false;
		}
		sharedTable.addResult("ipv6", ipv6Status);
		
		ConnectionStatus pingStatus = new ConnectionStatus();
		PingTester pingTester = new PingTester();
		try {
			pingStatus = pingTester.latencyTest("www.cs.columbia.edu");
		} catch (Exception e) {
			e.printStackTrace();
		}
		sharedTable.addResult("ping", pingStatus);
		
		ConnectionStatus ftpStatus = new ConnectionStatus();
		FTPConnectivity ftp = new FTPConnectivity();
		ftpStatus = ftp.runTests();
		sharedTable.addResult("ftp", ftpStatus);
		
		return sharedTable;
	}
	

} // end TestRunner class





class ResultsTable {
	
	private static int testsRun;
	private static Hashtable <String, ConnectionStatus> resultsTable = new Hashtable<String, ConnectionStatus>();
	
	public ResultsTable(){
	}
	
	public synchronized int numTestsRun(){
		return testsRun;
	}
	
	private synchronized void incrementTestCount(){
		testsRun++;
	}

	public synchronized void addResult(String key, ConnectionStatus status){		
		resultsTable.put(key, status); // add the result
		this.incrementTestCount();	// increment the number of tests run
	}
	
	public synchronized ConnectionStatus getConnectionStatus(String key) {
		return resultsTable.get(key);
	}
	
	public synchronized boolean allRed() {
		
		for (ConnectionStatus status : resultsTable.values()){
			if (!status.currentLightStatus.equals(ConnectionStatus.lights.RED))
				return false;
		}
		return true;
		
	}
	
	
	
} // end resultsTable